package com.itlong.cloud.property.service.impl;

import com.itlong.cloud.POJO.DTO.property.PropertyInspectOperateDTO;
import com.itlong.cloud.POJO.VO.property.PropertyInspectOperateVO;
import com.itlong.cloud.POJO.VO.property.PropertyInspectReportBasicDataVO;
import com.itlong.cloud.POJO.VO.property.PropertyInspectReportCountVO;
import com.itlong.cloud.POJO.VO.property.PropertyInspectStatisticsBasicDataVO;
import com.itlong.cloud.property.dao.IPropertyInspectOperateDao;
import com.itlong.cloud.property.service.IPropertyInspectOperateService;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.page.Page;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <desc>
 *      物业-巡检操作服务接口实现类
 * <desc/>
 *
 * @createDate 2019/12/26
 */
@Service
public class PropertyInspectOperateServiceImpl implements IPropertyInspectOperateService {

    private static final Logger LOG = LoggerFactory.getLogger(PropertyInspectOperateServiceImpl.class);

    @Autowired
    private IPropertyInspectOperateDao iPropertyInspectOperateDao;

    /**
     * <desc>
     *      列表查询历史数据信息
     * </desc>
     *
     * @return 列表数据
     * @author wangzhi
     * @createDate 2019/12/26
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<PropertyInspectOperateVO> getHistoricalDataPage(PropertyInspectOperateDTO propertyInspectOperateDTO) throws Exception {
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyInspectOperateDTO);
        Page<PropertyInspectOperateVO> page = new Page<>();
        page.getPage().setPageSize(propertyInspectOperateDTO.getPageSize());
        page.getPage().setCurrentPage(propertyInspectOperateDTO.getCurrentPage());
        params.put("startSlip", page.getPage().getStartSlip());
        params.put("pageSize", page.getPage().getPageSize());
        List<PropertyInspectOperateVO> propertyInspectOperateVOList = iPropertyInspectOperateDao.getHistoricalDataList(params);
        // 导出时只查列表，不用分页
        if (StringUtils.isBlank(propertyInspectOperateDTO.getPageMark())) {
            page.setRows(propertyInspectOperateVOList, propertyInspectOperateVOList.size());
        } else {
            page.setRows(propertyInspectOperateVOList, iPropertyInspectOperateDao.getHistoricalDataCount(params));
        }
        return page;
    }

    /**
     * <desc>
     *      列表查询巡检报告数据信息
     * </desc>
     *
     * @return 列表数据
     * @author wangzhi
     * @createDate 2019/12/30
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<PropertyInspectOperateVO> getReportPage(PropertyInspectOperateDTO propertyInspectOperateDTO) throws Exception {
        Date nowTime = new Date();
        SimpleDateFormat sdfDay = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        String nowDay = sdfDay.format(nowTime);
        Date nowDayTime = sdfDay.parse(nowDay);
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyInspectOperateDTO);
        Page<PropertyInspectOperateVO> page = new Page<>();
        page.getPage().setPageSize(propertyInspectOperateDTO.getPageSize());
        page.getPage().setCurrentPage(propertyInspectOperateDTO.getCurrentPage());
        List<PropertyInspectOperateVO> propertyInspectOperateVOList = new ArrayList<>();
        // 先查询巡检报告原始数据
        List<PropertyInspectReportBasicDataVO> propertyInspectReportBasicDataVOList = iPropertyInspectOperateDao.getReportBasicDataList(params);
        // 查询巡检记录数据对应次数
        List<PropertyInspectReportCountVO> propertyInspectReportCountVOList = iPropertyInspectOperateDao.getReportCountList(params);
        // 巡检记录对应次数放入map
        Map<String, Integer> countMap = new HashMap<>();
        if (propertyInspectReportCountVOList != null && !propertyInspectReportCountVOList.isEmpty()) {
            for (PropertyInspectReportCountVO propertyInspectReportCountVO : propertyInspectReportCountVOList) {
                countMap.put(propertyInspectReportCountVO.getInspectAreaId() + propertyInspectReportCountVO.getInspectPlanId() + propertyInspectReportCountVO.getInspectTime(),
                        propertyInspectReportCountVO.getArriveTimes());
            }
        }
        // 合格数据
        Integer passCount = 0;
        // 漏检数据
        Integer lossCount = 0;
        // 组装巡检报告数据
        if (propertyInspectReportBasicDataVOList != null && !propertyInspectReportBasicDataVOList.isEmpty()) {
            for (PropertyInspectReportBasicDataVO propertyInspectReportBasicDataVO : propertyInspectReportBasicDataVOList) {
                Date planStartTime = sdfDay.parse(propertyInspectReportBasicDataVO.getPlanStartTime());
                Date planEndTime = sdfDay.parse(propertyInspectReportBasicDataVO.getPlanEndTime());
                // 开始时间，取查询时间、计划开始时间的最大值，数据库已过滤计划开始时间小于或等于当前时间
                if (StringUtils.isNotBlank(propertyInspectOperateDTO.getStartTime()) && planStartTime.compareTo(sdfDay.parse(propertyInspectOperateDTO.getStartTime())) < 0) {
                    planStartTime = sdfDay.parse(propertyInspectOperateDTO.getStartTime());
                }
                // 结束时间，取当前时间、查询时间、计划结束时间的最小值
                if (StringUtils.isNotBlank(propertyInspectOperateDTO.getEndTime()) && planEndTime.compareTo(sdfDay.parse(propertyInspectOperateDTO.getEndTime())) > 0) {
                    planEndTime = sdfDay.parse(propertyInspectOperateDTO.getEndTime());
                }
                if (planEndTime.compareTo(nowDayTime) > 0) {
                    planEndTime = nowDayTime;
                }
                // 计算结束时间和开始时间的差值
                long differDay = (planEndTime.getTime() - planStartTime.getTime()) / (24 * 60 * 60 * 1000);
                if (differDay < 0) {
                    continue;
                }
                // 先设置天数单位，日期为结束时间减去该单位
                int unitDay = -1;
                // 时间倒序，从最后一天开始
                for (; differDay >= 0; differDay--) {
                    unitDay++;
                    // 计算此时处理的时间
                    calendar.setTime(planEndTime);
                    calendar.add(Calendar.DAY_OF_MONTH, unitDay * -1);
                    String handleTime = sdfDay.format(calendar.getTime());
                    // 判断这一天是否为休息时间
                    if ("1".equals(propertyInspectReportBasicDataVO.getRestType())) {
                        // 通过时间获取周日期
                        String week = DateUtil.getWeek(calendar.getTime());
                        if (propertyInspectReportBasicDataVO.getRestTimeFixed().contains(week)) {
                            continue;
                        }
                    } else if ("2".equals(propertyInspectReportBasicDataVO.getRestType())) {
                        if (propertyInspectReportBasicDataVO.getRestTimeAssign().contains(handleTime)) {
                            continue;
                        }
                    }
                    PropertyInspectOperateVO propertyInspectOperateVO = new PropertyInspectOperateVO();
                    propertyInspectOperateVO.setInspectAreaName(propertyInspectReportBasicDataVO.getInspectAreaName());
                    propertyInspectOperateVO.setRealName(propertyInspectReportBasicDataVO.getRealName());
                    propertyInspectOperateVO.setInspectPlanName(propertyInspectReportBasicDataVO.getInspectPlanName());
                    propertyInspectOperateVO.setStartTime(handleTime + " " + propertyInspectReportBasicDataVO.getDayStartTime());
                    propertyInspectOperateVO.setEndTime(handleTime + " " + propertyInspectReportBasicDataVO.getDayEndTime());
                    propertyInspectOperateVO.setPlanTimes(propertyInspectReportBasicDataVO.getTimes() == null ? 0 : propertyInspectReportBasicDataVO.getTimes());
                    Integer arriveTimes = countMap.get(propertyInspectReportBasicDataVO.getInspectAreaId() + propertyInspectReportBasicDataVO.getInspectPlanId() + handleTime);
                    propertyInspectOperateVO.setArriveTimes(arriveTimes == null ? 0 : arriveTimes);
                    int lossTimes = propertyInspectOperateVO.getPlanTimes() - propertyInspectOperateVO.getArriveTimes();
                    propertyInspectOperateVO.setLossTimes(lossTimes > 0 ? lossTimes : 0);
                    if (lossTimes > 0) {
                        lossCount++;
                    } else {
                        passCount++;
                    }
                    propertyInspectOperateVOList.add(propertyInspectOperateVO);
                }
            }
        }
        // 导出时只查列表，不用分页
        if (StringUtils.isNotBlank(propertyInspectOperateDTO.getPageMark())) {
            // 进行分页
            List<PropertyInspectOperateVO> propertyInspectOperateVORows = new ArrayList<>();
            for (int index = page.getPage().getStartSlip(); index < page.getPage().getStartSlip() + page.getPage().getPageSize(); index++) {
                if (propertyInspectOperateVOList.size() > index) {
                    propertyInspectOperateVORows.add(propertyInspectOperateVOList.get(index));
                } else {
                    break;
                }
            }
            if (!propertyInspectOperateVORows.isEmpty()) {
                Map<String, Object> expandMap = new HashMap<>();
                expandMap.put("passCount", passCount);
                expandMap.put("lossCount", lossCount);
                propertyInspectOperateVORows.get(0).setExpandMap(expandMap);
            }
            page.setRows(propertyInspectOperateVORows, propertyInspectOperateVOList.size());
        } else {
            page.setRows(propertyInspectOperateVOList, propertyInspectOperateVOList.size());
        }
        return page;
    }

    /**
     * <desc>
     *      查询统计数据信息
     * </desc>
     *
     * @return 统计数据信息
     * @author wangzhi
     * @createDate 2020/01/02
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<PropertyInspectOperateVO> getStatisticsData(PropertyInspectOperateDTO propertyInspectOperateDTO) throws Exception {
        // 统计类型 1按区域统计 2按人员统计 3按地点统计 4按计划名称统计，其中按人员统计先去掉不做，因为计划关联多个人时，多个人一起总共达到计划次数就行，漏巡率的计算对人员而言就不合理
        Date nowTime = new Date();
        SimpleDateFormat sdfDay = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        String nowDay = sdfDay.format(nowTime);
        Date nowDayTime = sdfDay.parse(nowDay);
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyInspectOperateDTO);
        List<PropertyInspectOperateVO> propertyInspectOperateVOList = new ArrayList<>();
        // 查询统计数据原始数据
        List<PropertyInspectStatisticsBasicDataVO> propertyInspectStatisticsBasicDataVOList = iPropertyInspectOperateDao.getStatisticsBasicDataList(params);
        // 查询巡检记录统计数据对应次数
        List<PropertyInspectReportCountVO> propertyInspectReportCountVOList = iPropertyInspectOperateDao.getStatisticsDataCountList(params);
        // 巡检记录对应次数放入map
        Map<String, Integer> countMap = new HashMap<>();
        if (propertyInspectReportCountVOList != null && !propertyInspectReportCountVOList.isEmpty()) {
            for (PropertyInspectReportCountVO propertyInspectReportCountVO : propertyInspectReportCountVOList) {
                countMap.put(propertyInspectReportCountVO.getInspectAreaId() + propertyInspectReportCountVO.getInspectPlanId() + propertyInspectReportCountVO.getInspectTime(),
                        propertyInspectReportCountVO.getArriveTimes());
            }
        }
        // 返回的统计数据承接map，用于对同一区域或巡检点但是又不同计划的合并操作
        Map<String, PropertyInspectOperateVO> propertyInspectOperateVOMap = new HashMap<>();
        // 组装统计数据
        if (propertyInspectStatisticsBasicDataVOList != null && !propertyInspectStatisticsBasicDataVOList.isEmpty()) {
            for (PropertyInspectStatisticsBasicDataVO propertyInspectStatisticsBasicDataVO : propertyInspectStatisticsBasicDataVOList) {
                Date planStartTime = sdfDay.parse(propertyInspectStatisticsBasicDataVO.getPlanStartTime());
                Date planEndTime = sdfDay.parse(propertyInspectStatisticsBasicDataVO.getPlanEndTime());
                // 开始时间，取查询时间、计划开始时间的最大值，数据库已过滤计划开始时间小于或等于当前时间
                if (StringUtils.isNotBlank(propertyInspectOperateDTO.getStartTime()) && planStartTime.compareTo(sdfDay.parse(propertyInspectOperateDTO.getStartTime())) < 0) {
                    planStartTime = sdfDay.parse(propertyInspectOperateDTO.getStartTime());
                }
                // 结束时间，取当前时间、查询时间、计划结束时间的最小值
                if (StringUtils.isNotBlank(propertyInspectOperateDTO.getEndTime()) && planEndTime.compareTo(sdfDay.parse(propertyInspectOperateDTO.getEndTime())) > 0) {
                    planEndTime = sdfDay.parse(propertyInspectOperateDTO.getEndTime());
                }
                if (planEndTime.compareTo(nowDayTime) > 0) {
                    planEndTime = nowDayTime;
                }
                // 计算结束时间和开始时间的差值
                long differDay = (planEndTime.getTime() - planStartTime.getTime()) / (24 * 60 * 60 * 1000);
                if (differDay < 0) {
                    continue;
                }
                // 计算当前这条数据的巡检计划的时间段内总次数
                Integer planTimes = 0;
                // 要规避巡检记录多于计划次数的情况
                Integer arriveTimes = 0;
                // 先设置天数单位，日期为结束时间减去该单位
                int unitDay = -1;
                // 时间倒序，从最后一天开始
                for (; differDay >= 0; differDay--) {
                    unitDay++;
                    // 计算此时处理的时间
                    calendar.setTime(planEndTime);
                    calendar.add(Calendar.DAY_OF_MONTH, unitDay * -1);
                    String handleTime = sdfDay.format(calendar.getTime());
                    // 判断这一天是否为休息时间
                    if ("1".equals(propertyInspectStatisticsBasicDataVO.getRestType())) {
                        // 通过时间获取周日期
                        String week = DateUtil.getWeek(calendar.getTime());
                        if (propertyInspectStatisticsBasicDataVO.getRestTimeFixed().contains(week)) {
                            continue;
                        }
                    } else if ("2".equals(propertyInspectStatisticsBasicDataVO.getRestType())) {
                        if (propertyInspectStatisticsBasicDataVO.getRestTimeAssign().contains(handleTime)) {
                            continue;
                        }
                    }
                    planTimes += propertyInspectStatisticsBasicDataVO.getTimes();
                    Integer recordCount = countMap.get(propertyInspectStatisticsBasicDataVO.getInspectAreaId() + propertyInspectStatisticsBasicDataVO.getInspectPlanId() + handleTime);
                    if (recordCount == null) {
                        arriveTimes += 0;
                    } else if (recordCount <= propertyInspectStatisticsBasicDataVO.getTimes()) {
                        arriveTimes += recordCount;
                    } else {
                        arriveTimes += propertyInspectStatisticsBasicDataVO.getTimes();
                    }
                }
                PropertyInspectOperateVO propertyInspectOperateVO = null;
                // 按区域统计
                if (propertyInspectOperateDTO.getStatType() == 1) {
                    propertyInspectOperateVO = propertyInspectOperateVOMap.get(propertyInspectStatisticsBasicDataVO.getInspectAreaId()) == null ?
                            new PropertyInspectOperateVO() : propertyInspectOperateVOMap.get(propertyInspectStatisticsBasicDataVO.getInspectAreaId());
                    propertyInspectOperateVO.setInspectAreaName(propertyInspectStatisticsBasicDataVO.getInspectAreaName());
                    propertyInspectOperateVO.setPlanTimes(propertyInspectOperateVO.getPlanTimes() == null ? planTimes : (propertyInspectOperateVO.getPlanTimes() + planTimes));
                    propertyInspectOperateVO.setArriveTimes(propertyInspectOperateVO.getArriveTimes() == null ? arriveTimes : (propertyInspectOperateVO.getArriveTimes() + arriveTimes));
                    propertyInspectOperateVOMap.put(propertyInspectStatisticsBasicDataVO.getInspectAreaId(), propertyInspectOperateVO);
                }
                // 按地点统计
                if (propertyInspectOperateDTO.getStatType() == 3) {
                    propertyInspectOperateVO = propertyInspectOperateVOMap.get(propertyInspectStatisticsBasicDataVO.getInspectPointId()) == null ?
                            new PropertyInspectOperateVO() : propertyInspectOperateVOMap.get(propertyInspectStatisticsBasicDataVO.getInspectPointId());
                    propertyInspectOperateVO.setAddressName(propertyInspectStatisticsBasicDataVO.getInspectPointName());
                    propertyInspectOperateVO.setPlanTimes(propertyInspectOperateVO.getPlanTimes() == null ? planTimes : (propertyInspectOperateVO.getPlanTimes() + planTimes));
                    propertyInspectOperateVO.setArriveTimes(propertyInspectOperateVO.getArriveTimes() == null ? arriveTimes : (propertyInspectOperateVO.getArriveTimes() + arriveTimes));
                    propertyInspectOperateVOMap.put(propertyInspectStatisticsBasicDataVO.getInspectPointId(), propertyInspectOperateVO);
                }
                // 按计划名称统计
                if (propertyInspectOperateDTO.getStatType() == 4) {
                    propertyInspectOperateVO = propertyInspectOperateVOMap.get(propertyInspectStatisticsBasicDataVO.getInspectPlanId()) == null ?
                            new PropertyInspectOperateVO() : propertyInspectOperateVOMap.get(propertyInspectStatisticsBasicDataVO.getInspectPlanId());
                    propertyInspectOperateVO.setInspectPlanName(propertyInspectStatisticsBasicDataVO.getInspectPlanName());
                    propertyInspectOperateVO.setPlanTimes(propertyInspectOperateVO.getPlanTimes() == null ? planTimes : (propertyInspectOperateVO.getPlanTimes() + planTimes));
                    propertyInspectOperateVO.setArriveTimes(propertyInspectOperateVO.getArriveTimes() == null ? arriveTimes : (propertyInspectOperateVO.getArriveTimes() + arriveTimes));
                    propertyInspectOperateVOMap.put(propertyInspectStatisticsBasicDataVO.getInspectPlanId(), propertyInspectOperateVO);
                }
                if (!propertyInspectOperateVOList.contains(propertyInspectOperateVO)) {
                    propertyInspectOperateVOList.add(propertyInspectOperateVO);
                }
            }
        }
        // 数字格式化对象
        NumberFormat numberFormat = NumberFormat.getInstance();
        numberFormat.setMaximumFractionDigits(2);
        if (!propertyInspectOperateVOList.isEmpty()) {
            // 计算漏检次数、合格率、漏巡率
            for (PropertyInspectOperateVO propertyInspectOperateVO : propertyInspectOperateVOList) {
                int lossTimes = propertyInspectOperateVO.getPlanTimes() - propertyInspectOperateVO.getArriveTimes();
                propertyInspectOperateVO.setLossTimes(lossTimes > 0 ? lossTimes : 0);
                // 规避到达次数比计划次数多的情况
                if (propertyInspectOperateVO.getPlanTimes() == 0) {
                    propertyInspectOperateVO.setPassPercent("0%");
                    propertyInspectOperateVO.setLossPercent("0%");
                } else {
                    float passPercent = (float) propertyInspectOperateVO.getArriveTimes() / (float) propertyInspectOperateVO.getPlanTimes() * 100;
                    passPercent = passPercent > 100f ? 100f : passPercent;
                    propertyInspectOperateVO.setPassPercent(numberFormat.format(passPercent) + "%");
                    propertyInspectOperateVO.setLossPercent(numberFormat.format(100f - passPercent) + "%");
                }
            }
        }
        return propertyInspectOperateVOList;
    }

    /**
     * <desc>
     *      巡检日历列表查询
     * </desc>
     *
     * @return 巡检日历列表
     * @author wangzhi
     * @createDate 2020/01/06
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<PropertyInspectOperateVO> getCalendarPage(PropertyInspectOperateDTO propertyInspectOperateDTO) throws Exception {
        Date nowTime = new Date();
        SimpleDateFormat sdfDay = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        String nowDay = sdfDay.format(nowTime);
        Date nowDayTime = sdfDay.parse(nowDay);
        // 按区域统计
        propertyInspectOperateDTO.setStatType(1);
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyInspectOperateDTO);
        Page<PropertyInspectOperateVO> page = new Page<>();
        page.getPage().setPageSize(propertyInspectOperateDTO.getPageSize());
        page.getPage().setCurrentPage(propertyInspectOperateDTO.getCurrentPage());
        List<PropertyInspectOperateVO> propertyInspectOperateVOList = new ArrayList<>();
        // 查询统计数据原始数据
        List<PropertyInspectStatisticsBasicDataVO> propertyInspectStatisticsBasicDataVOList = iPropertyInspectOperateDao.getStatisticsBasicDataList(params);
        // 查询巡检记录每一天的总次数
        List<PropertyInspectReportCountVO> propertyInspectReportCountVOList = iPropertyInspectOperateDao.getInspectDataDayCount(params);
        // 每一天对应次数放入map
        Map<String, Integer> countMap = new HashMap<>();
        if (propertyInspectReportCountVOList != null && !propertyInspectReportCountVOList.isEmpty()) {
            for (PropertyInspectReportCountVO propertyInspectReportCountVO : propertyInspectReportCountVOList) {
                countMap.put(propertyInspectReportCountVO.getInspectAreaId() + propertyInspectReportCountVO.getInspectPlanId() + propertyInspectReportCountVO.getInspectTime(),
                        propertyInspectReportCountVO.getArriveTimes());
            }
        }
        // 合格数据
        Integer passCount = 0;
        // 漏检数据
        Integer lossCount = 0;
        // 组装日期数据
        if (propertyInspectStatisticsBasicDataVOList != null && !propertyInspectStatisticsBasicDataVOList.isEmpty()) {
            // 先确定返回的列表的时间区间
            // 先取出原始数据中所有计划的最早开始时间和最晚结束时间
            Date planStartTime = null;
            Date planEndTime = null;
            for (PropertyInspectStatisticsBasicDataVO propertyInspectStatisticsBasicDataVO : propertyInspectStatisticsBasicDataVOList) {
                if (planStartTime == null || planStartTime.compareTo(sdfDay.parse(propertyInspectStatisticsBasicDataVO.getPlanStartTime())) > 0) {
                    planStartTime = sdfDay.parse(propertyInspectStatisticsBasicDataVO.getPlanStartTime());
                }
                if (planEndTime == null || planEndTime.compareTo(sdfDay.parse(propertyInspectStatisticsBasicDataVO.getPlanEndTime())) < 0) {
                    planEndTime = sdfDay.parse(propertyInspectStatisticsBasicDataVO.getPlanEndTime());
                }
            }
            // 开始时间，取查询时间、计划开始时间的最大值，数据库已过滤计划开始时间小于或等于当前时间
            if (StringUtils.isNotBlank(propertyInspectOperateDTO.getStartTime()) && planStartTime.compareTo(sdfDay.parse(propertyInspectOperateDTO.getStartTime())) < 0) {
                planStartTime = sdfDay.parse(propertyInspectOperateDTO.getStartTime());
            }
            // 结束时间，取当前时间、查询时间、计划结束时间的最小值
            if (StringUtils.isNotBlank(propertyInspectOperateDTO.getEndTime()) && planEndTime.compareTo(sdfDay.parse(propertyInspectOperateDTO.getEndTime())) > 0) {
                planEndTime = sdfDay.parse(propertyInspectOperateDTO.getEndTime());
            }
            if (planEndTime.compareTo(nowDayTime) > 0) {
                planEndTime = nowDayTime;
            }
            // 计算结束时间和开始时间的差值
            long differDay = (planEndTime.getTime() - planStartTime.getTime()) / (24 * 60 * 60 * 1000);
            if (differDay < 0) {
                page.setRows(propertyInspectOperateVOList, propertyInspectOperateVOList.size());
                return page;
            }
            // 先设置天数单位，日期为结束时间减去该单位
            int unitDay = -1;
            // 时间倒序，从最后一天开始
            for (; differDay >= 0; differDay--) {
                unitDay++;
                Integer planTimes = 0;
                // 要规避巡检记录多于计划次数的情况
                Integer arriveTimes = 0;
                // 计算此时处理的时间
                calendar.setTime(planEndTime);
                calendar.add(Calendar.DAY_OF_MONTH, unitDay * -1);
                String handleTime = sdfDay.format(calendar.getTime());
                for (PropertyInspectStatisticsBasicDataVO propertyInspectStatisticsBasicDataVO : propertyInspectStatisticsBasicDataVOList) {
                    // 判断当前日期是否在该计划时间区间内
                    if (calendar.getTime().compareTo(sdfDay.parse(propertyInspectStatisticsBasicDataVO.getPlanStartTime())) < 0 ||
                            calendar.getTime().compareTo(sdfDay.parse(propertyInspectStatisticsBasicDataVO.getPlanEndTime())) > 0) {
                        continue;
                    }
                    // 判断这一天是否为休息时间
                    if ("1".equals(propertyInspectStatisticsBasicDataVO.getRestType())) {
                        // 通过时间获取周日期
                        String week = DateUtil.getWeek(calendar.getTime());
                        if (propertyInspectStatisticsBasicDataVO.getRestTimeFixed().contains(week)) {
                            continue;
                        }
                    } else if ("2".equals(propertyInspectStatisticsBasicDataVO.getRestType())) {
                        if (propertyInspectStatisticsBasicDataVO.getRestTimeAssign().contains(handleTime)) {
                            continue;
                        }
                    }
                    planTimes += propertyInspectStatisticsBasicDataVO.getTimes();
                    Integer recordCount = countMap.get(propertyInspectStatisticsBasicDataVO.getInspectAreaId() + propertyInspectStatisticsBasicDataVO.getInspectPlanId() + handleTime);
                    if (recordCount == null) {
                        arriveTimes += 0;
                    } else if (recordCount <= propertyInspectStatisticsBasicDataVO.getTimes()) {
                        arriveTimes += recordCount;
                    } else {
                        arriveTimes += propertyInspectStatisticsBasicDataVO.getTimes();
                    }
                }
                if (planTimes == 0) {
                    continue;
                }
                PropertyInspectOperateVO propertyInspectOperateVO = new PropertyInspectOperateVO();
                propertyInspectOperateVO.setDate(handleTime);
                propertyInspectOperateVO.setPlanTimes(planTimes);
                propertyInspectOperateVO.setArriveTimes(arriveTimes == null ? 0 : arriveTimes);
                int lossTimes = propertyInspectOperateVO.getPlanTimes() - propertyInspectOperateVO.getArriveTimes();
                propertyInspectOperateVO.setLossTimes(lossTimes > 0 ? lossTimes : 0);
                if (lossTimes > 0) {
                    lossCount++;
                } else {
                    passCount++;
                }
                propertyInspectOperateVOList.add(propertyInspectOperateVO);
            }
        }
        // 导出时只查列表，不用分页
        if (StringUtils.isNotBlank(propertyInspectOperateDTO.getPageMark())) {
            // 进行分页
            List<PropertyInspectOperateVO> propertyInspectOperateVORows = new ArrayList<>();
            for (int index = page.getPage().getStartSlip(); index < page.getPage().getStartSlip() + page.getPage().getPageSize(); index++) {
                if (propertyInspectOperateVOList.size() > index) {
                    propertyInspectOperateVORows.add(propertyInspectOperateVOList.get(index));
                } else {
                    break;
                }
            }
            if (!propertyInspectOperateVORows.isEmpty()) {
                Map<String, Object> expandMap = new HashMap<>();
                expandMap.put("passCount", passCount);
                expandMap.put("lossCount", lossCount);
                propertyInspectOperateVORows.get(0).setExpandMap(expandMap);
            }
            page.setRows(propertyInspectOperateVORows, propertyInspectOperateVOList.size());
        } else {
            page.setRows(propertyInspectOperateVOList, propertyInspectOperateVOList.size());
        }
        return page;
    }

    /**
     * <desc>
     *      查看巡检日历数据信息详情
     * </desc>
     *
     * @return 巡检日历数据信息详情
     * @author wangzhi
     * @createDate 2020/01/06
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<PropertyInspectOperateVO> getCalendarDetails(PropertyInspectOperateDTO propertyInspectOperateDTO) throws Exception {
        SimpleDateFormat sdfDay = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat sdfTime = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Date paramDate = sdfDay.parse(propertyInspectOperateDTO.getDate());
        // 按地点统计
        propertyInspectOperateDTO.setStatType(3);
        propertyInspectOperateDTO.setStartTime(propertyInspectOperateDTO.getDate() + " 00:00:00");
        propertyInspectOperateDTO.setEndTime(propertyInspectOperateDTO.getDate() + " 23:59:59");
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyInspectOperateDTO);
        Page<PropertyInspectOperateVO> page = new Page<>();
        page.getPage().setPageSize(propertyInspectOperateDTO.getPageSize());
        page.getPage().setCurrentPage(propertyInspectOperateDTO.getCurrentPage());
        List<PropertyInspectOperateVO> propertyInspectOperateVOList = new ArrayList<>();
        // 查询统计数据原始数据
        List<PropertyInspectStatisticsBasicDataVO> propertyInspectStatisticsBasicDataVOList = iPropertyInspectOperateDao.getStatisticsBasicDataList(params);
        // 查询巡检记录统计数据对应次数
        List<PropertyInspectReportCountVO> propertyInspectReportCountVOList = iPropertyInspectOperateDao.getStatisticsDataCountList(params);
        // 巡检记录对应次数放入map
        Map<String, Integer> countMap = new HashMap<>();
        if (propertyInspectReportCountVOList != null && !propertyInspectReportCountVOList.isEmpty()) {
            for (PropertyInspectReportCountVO propertyInspectReportCountVO : propertyInspectReportCountVOList) {
                countMap.put(propertyInspectReportCountVO.getInspectPointId() + propertyInspectReportCountVO.getInspectPlanId(), propertyInspectReportCountVO.getArriveTimes());
            }
        }
        // 返回的统计数据承接map，用于对同一区域或巡检点但是又不同计划的合并操作
        Map<String, PropertyInspectOperateVO> propertyInspectOperateVOMap = new HashMap<>();
        // 组装统计数据
        if (propertyInspectStatisticsBasicDataVOList != null && !propertyInspectStatisticsBasicDataVOList.isEmpty()) {
            for (PropertyInspectStatisticsBasicDataVO propertyInspectStatisticsBasicDataVO : propertyInspectStatisticsBasicDataVOList) {
                // 判断所选日期是否在该计划时间区间内
                if (paramDate.compareTo(sdfDay.parse(propertyInspectStatisticsBasicDataVO.getPlanStartTime())) < 0 ||
                        paramDate.compareTo(sdfDay.parse(propertyInspectStatisticsBasicDataVO.getPlanEndTime())) > 0) {
                    continue;
                }
                // 判断这一天是否为休息时间
                if ("1".equals(propertyInspectStatisticsBasicDataVO.getRestType())) {
                    // 通过时间获取周日期
                    String week = DateUtil.getWeek(paramDate);
                    if (propertyInspectStatisticsBasicDataVO.getRestTimeFixed().contains(week)) {
                        continue;
                    }
                } else if ("2".equals(propertyInspectStatisticsBasicDataVO.getRestType())) {
                    if (propertyInspectStatisticsBasicDataVO.getRestTimeAssign().contains(propertyInspectOperateDTO.getDate())) {
                        continue;
                    }
                }
                PropertyInspectOperateVO propertyInspectOperateVO = propertyInspectOperateVOMap.get(propertyInspectStatisticsBasicDataVO.getInspectPointId()) == null ?
                        new PropertyInspectOperateVO() : propertyInspectOperateVOMap.get(propertyInspectStatisticsBasicDataVO.getInspectPointId());
                propertyInspectOperateVO.setInspectAreaName(propertyInspectStatisticsBasicDataVO.getInspectAreaName());
                propertyInspectOperateVO.setAddressName(propertyInspectStatisticsBasicDataVO.getInspectPointName());
                propertyInspectOperateVO.setRealName(propertyInspectStatisticsBasicDataVO.getRealName());
                // 时间取该点对应所有计划的合并时间区间
                String startTime = propertyInspectOperateDTO.getDate() + " " + propertyInspectStatisticsBasicDataVO.getDayStartTime();
                if (StringUtils.isBlank(propertyInspectOperateVO.getStartTime()) || sdfTime.parse(propertyInspectOperateVO.getStartTime()).compareTo(sdfTime.parse(startTime)) > 0) {
                    propertyInspectOperateVO.setStartTime(startTime);
                }
                String endTime = propertyInspectOperateDTO.getDate() + " " + propertyInspectStatisticsBasicDataVO.getDayEndTime();
                if (StringUtils.isBlank(propertyInspectOperateVO.getEndTime()) || sdfTime.parse(propertyInspectOperateVO.getEndTime()).compareTo(sdfTime.parse(endTime)) < 0) {
                    propertyInspectOperateVO.setEndTime(endTime);
                }
                propertyInspectOperateVO.setPlanTimes(propertyInspectOperateVO.getPlanTimes() == null ?
                        propertyInspectStatisticsBasicDataVO.getTimes() : (propertyInspectOperateVO.getPlanTimes() + propertyInspectStatisticsBasicDataVO.getTimes()));
                // 要规避巡检记录多于计划次数的情况
                Integer arriveTimes = countMap.get(propertyInspectStatisticsBasicDataVO.getInspectPointId() + propertyInspectStatisticsBasicDataVO.getInspectPlanId());
                if (arriveTimes == null) {
                    arriveTimes = 0;
                } else if (arriveTimes > propertyInspectStatisticsBasicDataVO.getTimes()) {
                    arriveTimes = propertyInspectStatisticsBasicDataVO.getTimes();
                }
                propertyInspectOperateVO.setArriveTimes(propertyInspectOperateVO.getArriveTimes() == null ? arriveTimes : (propertyInspectOperateVO.getArriveTimes() + arriveTimes));
                propertyInspectOperateVOMap.put(propertyInspectStatisticsBasicDataVO.getInspectPointId(), propertyInspectOperateVO);
                if (!propertyInspectOperateVOList.contains(propertyInspectOperateVO)) {
                    propertyInspectOperateVOList.add(propertyInspectOperateVO);
                }
            }
        }
        if (!propertyInspectOperateVOList.isEmpty()) {
            // 计算状态
            for (PropertyInspectOperateVO propertyInspectOperateVO : propertyInspectOperateVOList) {
                int lossTimes = propertyInspectOperateVO.getPlanTimes() - propertyInspectOperateVO.getArriveTimes();
                propertyInspectOperateVO.setLossTimes(lossTimes > 0 ? lossTimes : 0);
                propertyInspectOperateVO.setStatus(lossTimes > 0 ? 2 : 1);
            }
        }
        // 进行分页
        List<PropertyInspectOperateVO> propertyInspectOperateVORows = new ArrayList<>();
        for (int index = page.getPage().getStartSlip(); index < page.getPage().getStartSlip() + page.getPage().getPageSize(); index++) {
            if (propertyInspectOperateVOList.size() > index) {
                propertyInspectOperateVORows.add(propertyInspectOperateVOList.get(index));
            } else {
                break;
            }
        }
        page.setRows(propertyInspectOperateVORows, propertyInspectOperateVOList.size());
        return page;
    }

    /**
     * <desc>
     *      报警数据列表查询
     * </desc>
     *
     * @return 报警数据列表
     * @author wangzhi
     * @createDate 2020/01/07
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<PropertyInspectOperateVO> getAlarmPage(PropertyInspectOperateDTO propertyInspectOperateDTO) throws Exception {
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(propertyInspectOperateDTO);
        Page<PropertyInspectOperateVO> page = new Page<>();
        page.getPage().setPageSize(propertyInspectOperateDTO.getPageSize());
        page.getPage().setCurrentPage(propertyInspectOperateDTO.getCurrentPage());
        params.put("startSlip", page.getPage().getStartSlip());
        params.put("pageSize", page.getPage().getPageSize());
        List<PropertyInspectOperateVO> propertyInspectOperateVOList = iPropertyInspectOperateDao.getAlarmPage(params);
        // 导出时只查列表，不用分页
        if (StringUtils.isBlank(propertyInspectOperateDTO.getPageMark())) {
            page.setRows(propertyInspectOperateVOList, propertyInspectOperateVOList.size());
        } else {
            page.setRows(propertyInspectOperateVOList, iPropertyInspectOperateDao.getAlarmCount(params));
        }
        return page;
    }
}
